{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torchvision\n",
    "import torch.nn.functional as F\n",
    "from torchvision.datasets import ImageFolder\n",
    "import torch.utils.data as Data\n",
    "import torchvision.transforms as transforms\n",
    "import time # 导入模块\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ResidualBlock(nn.Module):\n",
    "    def __init__(self, inchannel, outchannel, stride = 1):\n",
    "        super(ResidualBlock, self).__init__()\n",
    "        self.left = nn.Sequential(\n",
    "            nn.Conv2d(inchannel, outchannel, kernel_size=3, stride=stride, padding=1, bias=False),\n",
    "            nn.BatchNorm2d(outchannel),\n",
    "            nn.ReLU(inplace=True),\n",
    "            nn.Conv2d(outchannel, outchannel, kernel_size=3, stride=1, padding=1, bias=False),\n",
    "            nn.BatchNorm2d(outchannel)\n",
    "        )\n",
    "        self.shortcut =  nn.Sequential()\n",
    "        if stride != 1 or inchannel != outchannel:\n",
    "            self.shortcut = nn.Sequential(\n",
    "                nn.Conv2d(inchannel, outchannel, kernel_size=1, stride=stride, bias=False),\n",
    "                nn.BatchNorm2d(outchannel)\n",
    "            )\n",
    "\n",
    "    def forward(self,x):\n",
    "        out = self.left(x)\n",
    "        out += self.shortcut(x)\n",
    "        out = F.relu(out)\n",
    "        return out"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "class squeeze(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(squeeze, self).__init__()\n",
    "    def forward(self,x):\n",
    "        out = x.squeeze()  # squeeze 去除所有item数量为1的维度\n",
    "        return out"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "ResNet = nn.Sequential(\n",
    "    nn.Conv2d(3, 64,kernel_size=3, stride=1, padding=1, bias=False),\n",
    "    ResidualBlock(64,64, stride=1),\n",
    "    ResidualBlock(64,64, stride=1),\n",
    "    ResidualBlock(64,128, stride=2),\n",
    "    ResidualBlock(128,128, stride=1),\n",
    "    ResidualBlock(128,256, stride=2),\n",
    "    ResidualBlock(256,256, stride=1),\n",
    "    ResidualBlock(256,512, stride=2),\n",
    "    ResidualBlock(512,512, stride=1),\n",
    "    nn.AvgPool2d(kernel_size=5),\n",
    "    squeeze(),  # squeeze 去除所有item数量为1的维度\n",
    "    nn.Linear(in_features=512,out_features=3)\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train_epoch(net, data_loader, device):\n",
    "    net.train()\n",
    "    train_batch_num = len(data_loader)\n",
    "    total_loss = 0\n",
    "    correct = 0\n",
    "    sample_num = 0\n",
    "\n",
    "    for batch_idx, (data, target) in enumerate(data_loader):\n",
    "        # print(data)\n",
    "        # print(target)\n",
    "        data = data.to(device).float()\n",
    "        target = target.to(device).long()\n",
    "        optimizer.zero_grad()\n",
    "        output = net(data)\n",
    "#         print(\"output\", output.shape)\n",
    "        loss = criterion(output, target)\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "        total_loss += loss.item()\n",
    "        prediction = torch.argmax(output, 1)\n",
    "#         print(\"output\", output)\n",
    "#         print(\"prediction\", prediction)\n",
    "#         print(\"target\", target)\n",
    "        correct += (prediction == target).sum().item()\n",
    "        sample_num += len(prediction)\n",
    "    loss = total_loss / train_batch_num\n",
    "    acc = correct / sample_num\n",
    "    return loss, acc\n",
    "\n",
    "def test_epoch(net, data_loader, device):\n",
    "    net.eval()\n",
    "    test_batch_num = len(data_loader)\n",
    "    total_loss = 0\n",
    "    correct = 0\n",
    "    sample_num = 0\n",
    "    with torch.no_grad():\n",
    "        for batch_idx, (data, target) in enumerate(data_loader):\n",
    "            data = data.to(device).float()\n",
    "            target = target.to(device).long()\n",
    "            output = net(data)\n",
    "            loss = criterion(output, target)\n",
    "            total_loss += loss.item()\n",
    "            prediction = torch.argmax(output, 1)\n",
    "            correct += (prediction == target).sum().item()\n",
    "            sample_num += len(prediction)\n",
    "    loss = total_loss / test_batch_num\n",
    "    acc = correct / sample_num\n",
    "    return loss, acc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "962\n",
      "340\n",
      "torch.Size([3, 64, 64])\n",
      "{'bus': 0, 'car': 1, 'truck': 2}\n",
      "torch.Size([3, 64, 64])\n",
      "{'bus': 0, 'car': 1, 'truck': 2}\n"
     ]
    }
   ],
   "source": [
    "data_transform = transforms.Compose([\n",
    "    transforms.Resize((64,64)),\n",
    "    transforms.ToTensor(),\n",
    "    transforms.Normalize(mean=[0.5,0.5,0.5], std=[0.5, 0.5, 0.5])\n",
    "])\n",
    "BATCH_SIZE = 128\n",
    "train_dataset = ImageFolder(\"vehicle_dataset_new/training_dataset\",transform = data_transform)\n",
    "train_loader = Data.DataLoader(dataset=train_dataset, batch_size=BATCH_SIZE, shuffle=True)\n",
    "\n",
    "test_dataset = ImageFolder(\"vehicle_dataset_new/test_dataset\",transform = data_transform)\n",
    "test_loader = Data.DataLoader(dataset=test_dataset, batch_size=BATCH_SIZE, shuffle=True)\n",
    "print(len(train_dataset))\n",
    "print(len(test_dataset))\n",
    "print(train_dataset[0][0].size())\n",
    "print(train_dataset.class_to_idx)\n",
    "print(test_dataset[0][0].size())\n",
    "print(test_dataset.class_to_idx)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "开始训练------0-------------\n",
      "epoch:0\t train_loss:1.2872 \ttrain_acc: 0.5904 \ttest_loss: 2.6954 \t test_acc: 0.1618 \t training_time: 71.59\n",
      "开始训练------1-------------\n",
      "epoch:1\t train_loss:0.5404 \ttrain_acc: 0.7973 \ttest_loss: 7.5591 \t test_acc: 0.3088 \t training_time: 68.98\n",
      "开始训练------2-------------\n",
      "epoch:2\t train_loss:0.4376 \ttrain_acc: 0.8378 \ttest_loss: 2.4373 \t test_acc: 0.4824 \t training_time: 69.02\n",
      "开始训练------3-------------\n",
      "epoch:3\t train_loss:0.3713 \ttrain_acc: 0.8472 \ttest_loss: 0.4745 \t test_acc: 0.8353 \t training_time: 68.74\n",
      "开始训练------4-------------\n",
      "epoch:4\t train_loss:0.3411 \ttrain_acc: 0.8701 \ttest_loss: 0.4987 \t test_acc: 0.8176 \t training_time: 69.28\n",
      "开始训练------5-------------\n",
      "epoch:5\t train_loss:0.3054 \ttrain_acc: 0.8742 \ttest_loss: 0.4104 \t test_acc: 0.8412 \t training_time: 69.78\n",
      "开始训练------6-------------\n",
      "epoch:6\t train_loss:0.2939 \ttrain_acc: 0.8909 \ttest_loss: 0.7872 \t test_acc: 0.7706 \t training_time: 69.40\n",
      "开始训练------7-------------\n",
      "epoch:7\t train_loss:0.2677 \ttrain_acc: 0.9033 \ttest_loss: 0.4660 \t test_acc: 0.8353 \t training_time: 69.63\n",
      "开始训练------8-------------\n",
      "epoch:8\t train_loss:0.2442 \ttrain_acc: 0.9096 \ttest_loss: 0.4707 \t test_acc: 0.8353 \t training_time: 69.61\n",
      "开始训练------9-------------\n",
      "epoch:9\t train_loss:0.2436 \ttrain_acc: 0.9085 \ttest_loss: 0.3980 \t test_acc: 0.8265 \t training_time: 68.96\n",
      "开始训练------10-------------\n",
      "epoch:10\t train_loss:0.2708 \ttrain_acc: 0.8960 \ttest_loss: 0.4398 \t test_acc: 0.8471 \t training_time: 69.35\n",
      "开始训练------11-------------\n",
      "epoch:11\t train_loss:0.2795 \ttrain_acc: 0.8960 \ttest_loss: 0.6494 \t test_acc: 0.7941 \t training_time: 69.21\n",
      "开始训练------12-------------\n",
      "epoch:12\t train_loss:0.2521 \ttrain_acc: 0.9064 \ttest_loss: 0.7190 \t test_acc: 0.7794 \t training_time: 69.33\n",
      "开始训练------13-------------\n",
      "epoch:13\t train_loss:0.2171 \ttrain_acc: 0.9220 \ttest_loss: 0.4424 \t test_acc: 0.8588 \t training_time: 69.12\n",
      "开始训练------14-------------\n",
      "epoch:14\t train_loss:0.1760 \ttrain_acc: 0.9459 \ttest_loss: 0.3358 \t test_acc: 0.8735 \t training_time: 69.20\n",
      "开始训练------15-------------\n",
      "epoch:15\t train_loss:0.1733 \ttrain_acc: 0.9387 \ttest_loss: 0.3751 \t test_acc: 0.8529 \t training_time: 69.08\n",
      "开始训练------16-------------\n",
      "epoch:16\t train_loss:0.1842 \ttrain_acc: 0.9304 \ttest_loss: 0.4391 \t test_acc: 0.8412 \t training_time: 68.66\n",
      "开始训练------17-------------\n",
      "epoch:17\t train_loss:0.1676 \ttrain_acc: 0.9376 \ttest_loss: 0.3080 \t test_acc: 0.9000 \t training_time: 69.24\n",
      "开始训练------18-------------\n",
      "epoch:18\t train_loss:0.1365 \ttrain_acc: 0.9543 \ttest_loss: 0.4351 \t test_acc: 0.8647 \t training_time: 69.19\n",
      "开始训练------19-------------\n",
      "epoch:19\t train_loss:0.1441 \ttrain_acc: 0.9470 \ttest_loss: 0.6961 \t test_acc: 0.8471 \t training_time: 69.10\n"
     ]
    }
   ],
   "source": [
    "num_classes = 3\n",
    "epochs = 20\n",
    "lr = 0.001\n",
    "device = torch.device('cpu')\n",
    "# device = torch.device('cuda')\n",
    "\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "optimizer = torch.optim.Adam(ResNet.parameters(), lr = lr)\n",
    "\n",
    "train_loss_list = []\n",
    "train_acc_list = []\n",
    "test_loss_list = []\n",
    "test_acc_list = []\n",
    "training_time_list = []\n",
    "for epoch in range(epochs):\n",
    "    print(\"开始训练------\" + str(epoch) + \"-------------\")\n",
    "\n",
    "    start = time.time()  #开始时间\n",
    "    train_loss, train_acc = train_epoch(ResNet, data_loader=train_loader, device=device)\n",
    "    end = time.time()  #结束时间\n",
    "    test_loss, test_acc = 0, 0\n",
    "    test_loss, test_acc  = test_epoch(ResNet, data_loader=test_loader, device=device)\n",
    "    train_loss_list.append(train_loss)\n",
    "    train_acc_list.append(train_acc)\n",
    "    test_loss_list.append(test_loss)\n",
    "    test_acc_list.append(test_acc)\n",
    "    training_time_list.append(end - start)\n",
    "    print(f\"epoch:{epoch}\\t train_loss:{train_loss:.4f} \\t\"\n",
    "          f\"train_acc: {train_acc:.4f} \\t\"\n",
    "          f\"test_loss: {test_loss:.4f} \\t test_acc: {test_acc:.4f} \\t training_time: {end-start:.2f}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "开始训练------0-------------\n",
      "epoch:0\t train_loss:0.1445 \ttrain_acc: 0.9459 \ttest_loss: 0.3705 \t test_acc: 0.8706 \t training_time: 68.94\n",
      "开始训练------1-------------\n",
      "epoch:1\t train_loss:0.1207 \ttrain_acc: 0.9626 \ttest_loss: 0.3298 \t test_acc: 0.8882 \t training_time: 68.99\n",
      "开始训练------2-------------\n",
      "epoch:3\t train_loss:0.1067 \ttrain_acc: 0.9563 \ttest_loss: 0.3411 \t test_acc: 0.8853 \t training_time: 68.97\n",
      "开始训练------4-------------\n",
      "epoch:4\t train_loss:0.0952 \ttrain_acc: 0.9605 \ttest_loss: 0.3620 \t test_acc: 0.8765 \t training_time: 68.97\n",
      "开始训练------5-------------\n",
      "epoch:5\t train_loss:0.0651 \ttrain_acc: 0.9719 \ttest_loss: 0.3217 \t test_acc: 0.8941 \t training_time: 69.01\n",
      "开始训练------6-------------\n",
      "epoch:6\t train_loss:0.0569 \ttrain_acc: 0.9823 \ttest_loss: 0.4308 \t test_acc: 0.8676 \t training_time: 69.24\n",
      "开始训练------7-------------\n",
      "epoch:7\t train_loss:0.0530 \ttrain_acc: 0.9792 \ttest_loss: 0.3102 \t test_acc: 0.9118 \t training_time: 69.04\n",
      "开始训练------8-------------\n",
      "epoch:8\t train_loss:0.0873 \ttrain_acc: 0.9657 \ttest_loss: 0.4231 \t test_acc: 0.8824 \t training_time: 69.44\n",
      "开始训练------9-------------\n",
      "epoch:9\t train_loss:0.0646 \ttrain_acc: 0.9761 \ttest_loss: 0.4426 \t test_acc: 0.8735 \t training_time: 69.72\n",
      "开始训练------10-------------\n",
      "epoch:10\t train_loss:0.1487 \ttrain_acc: 0.9491 \ttest_loss: 1.9990 \t test_acc: 0.7735 \t training_time: 69.23\n",
      "开始训练------11-------------\n",
      "epoch:11\t train_loss:0.1371 \ttrain_acc: 0.9501 \ttest_loss: 0.4978 \t test_acc: 0.8588 \t training_time: 68.38\n",
      "开始训练------12-------------\n",
      "epoch:12\t train_loss:0.1026 \ttrain_acc: 0.9595 \ttest_loss: 0.3394 \t test_acc: 0.8735 \t training_time: 69.12\n",
      "开始训练------13-------------\n",
      "epoch:15\t train_loss:0.0263 \ttrain_acc: 0.9906 \ttest_loss: 0.3759 \t test_acc: 0.8853 \t training_time: 69.08\n",
      "开始训练------16-------------\n",
      "epoch:16\t train_loss:0.0387 \ttrain_acc: 0.9875 \ttest_loss: 0.4283 \t test_acc: 0.8941 \t training_time: 69.64\n",
      "开始训练------17-------------\n",
      "epoch:17\t train_loss:0.0291 \ttrain_acc: 0.9896 \ttest_loss: 0.3036 \t test_acc: 0.9088 \t training_time: 69.24\n",
      "开始训练------18-------------\n",
      "epoch:18\t train_loss:0.0305 \ttrain_acc: 0.9886 \ttest_loss: 0.3601 \t test_acc: 0.8971 \t training_time: 68.88\n",
      "开始训练------19-------------\n",
      "epoch:19\t train_loss:0.0251 \ttrain_acc: 0.9917 \ttest_loss: 0.2904 \t test_acc: 0.9147 \t training_time: 69.16\n"
     ]
    }
   ],
   "source": [
    "for epoch in range(epochs):\n",
    "    print(\"开始训练------\" + str(epoch) + \"-------------\")\n",
    "\n",
    "    start = time.time()  #开始时间\n",
    "    train_loss, train_acc = train_epoch(ResNet, data_loader=train_loader, device=device)\n",
    "    end = time.time()  #结束时间\n",
    "    test_loss, test_acc = 0, 0\n",
    "    test_loss, test_acc  = test_epoch(ResNet, data_loader=test_loader, device=device)\n",
    "    train_loss_list.append(train_loss)\n",
    "    train_acc_list.append(train_acc)\n",
    "    test_loss_list.append(test_loss)\n",
    "    test_acc_list.append(test_acc)\n",
    "    training_time_list.append(end - start)\n",
    "    print(f\"epoch:{epoch}\\t train_loss:{train_loss:.4f} \\t\"\n",
    "          f\"train_acc: {train_acc:.4f} \\t\"\n",
    "          f\"test_loss: {test_loss:.4f} \\t test_acc: {test_acc:.4f} \\t training_time: {end-start:.2f}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.5904365904365905, 0.7972972972972973, 0.8378378378378378, 0.8471933471933472, 0.8700623700623701, 0.8742203742203742, 0.8908523908523909, 0.9033264033264033, 0.9095634095634095, 0.9085239085239085, 0.896049896049896, 0.896049896049896, 0.9064449064449065, 0.922037422037422, 0.9459459459459459, 0.9386694386694386, 0.9303534303534303, 0.9376299376299376, 0.9542619542619543, 0.946985446985447, 0.9459459459459459, 0.9625779625779626, 0.9667359667359667, 0.9563409563409564, 0.9604989604989606, 0.9719334719334719, 0.9823284823284824, 0.9792099792099792, 0.9656964656964657, 0.9760914760914761, 0.9490644490644491, 0.9501039501039501, 0.9594594594594594, 0.9781704781704782, 0.9802494802494802, 0.9906444906444907, 0.9875259875259875, 0.9896049896049897, 0.9885654885654885, 0.9916839916839917]\n"
     ]
    }
   ],
   "source": [
    "print(train_acc_list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 4 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "def plot(train_loss_list,label,title, subplot):\n",
    "    ax1 = plt.subplot(subplot)\n",
    "    plt.plot(list(range(len(train_loss_list))),train_loss_list, label=label)\n",
    "    ax1.set_title(title)\n",
    "    ax1.legend()\n",
    "#     plt.title(title)\n",
    "#     plt.legend()\n",
    "#     plt.show()\n",
    "plot(train_loss_list,\"train loss\",\"train loss\", 221)\n",
    "plot(test_loss_list,\"test loss\",\"test loss\", 222)\n",
    "plot(train_acc_list,\"train acc\",\"train acc\", 223)\n",
    "plot(test_acc_list,\"test acc\",\"test acc\", 224)\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1.2871705815196037, 0.5404373221099377, 0.4375697486102581, 0.3713027611374855, 0.34112206660211086, 0.3053721450269222, 0.2938588634133339, 0.26766442134976387, 0.24421825632452965, 0.24362517334520817, 0.2707857470959425, 0.27948467060923576, 0.25214717350900173, 0.21705567836761475, 0.17598190810531378, 0.1733233043923974, 0.1841593375429511, 0.1676081409677863, 0.13651856500655413, 0.1441438589245081, 0.14451556652784348, 0.12074188468977809, 0.0950296651571989, 0.10667760344222188, 0.09522669203579426, 0.06510751275345683, 0.05689240479841828, 0.052997784689068794, 0.08726318296976388, 0.06464753998443484, 0.14869103953242302, 0.13708128174766898, 0.10255737649276853, 0.0659274565987289, 0.04728473839350045, 0.026268013869412243, 0.03866538216243498, 0.029136331169866025, 0.0304975044564344, 0.02509282744722441]\n",
      "[2.6954458157221475, 7.559090614318848, 2.4372878074645996, 0.4744510352611542, 0.49868860840797424, 0.41037572423617047, 0.7871576348940531, 0.4659639398256938, 0.47072064876556396, 0.39803309241930646, 0.43981579939524335, 0.6494256456693014, 0.7190084854761759, 0.4424233039220174, 0.3357935845851898, 0.3750667671362559, 0.43908589084943134, 0.3079911271731059, 0.43506287535031635, 0.696078896522522, 0.3705279628435771, 0.3298095961411794, 0.32889120777448017, 0.34110090136528015, 0.3619772146145503, 0.3217207243045171, 0.43077202637990314, 0.31022554139296216, 0.4231499433517456, 0.44263915220896405, 1.9990291595458984, 0.4977623025576274, 0.33941705028216046, 0.5049541294574738, 0.571135958035787, 0.3758801172176997, 0.4282519519329071, 0.3036195983489354, 0.36009953419367474, 0.2903718153635661]\n",
      "[0.5904365904365905, 0.7972972972972973, 0.8378378378378378, 0.8471933471933472, 0.8700623700623701, 0.8742203742203742, 0.8908523908523909, 0.9033264033264033, 0.9095634095634095, 0.9085239085239085, 0.896049896049896, 0.896049896049896, 0.9064449064449065, 0.922037422037422, 0.9459459459459459, 0.9386694386694386, 0.9303534303534303, 0.9376299376299376, 0.9542619542619543, 0.946985446985447, 0.9459459459459459, 0.9625779625779626, 0.9667359667359667, 0.9563409563409564, 0.9604989604989606, 0.9719334719334719, 0.9823284823284824, 0.9792099792099792, 0.9656964656964657, 0.9760914760914761, 0.9490644490644491, 0.9501039501039501, 0.9594594594594594, 0.9781704781704782, 0.9802494802494802, 0.9906444906444907, 0.9875259875259875, 0.9896049896049897, 0.9885654885654885, 0.9916839916839917]\n",
      "[0.16176470588235295, 0.3088235294117647, 0.4823529411764706, 0.8352941176470589, 0.8176470588235294, 0.8411764705882353, 0.7705882352941177, 0.8352941176470589, 0.8352941176470589, 0.8264705882352941, 0.8470588235294118, 0.7941176470588235, 0.7794117647058824, 0.8588235294117647, 0.8735294117647059, 0.8529411764705882, 0.8411764705882353, 0.9, 0.8647058823529412, 0.8470588235294118, 0.8705882352941177, 0.888235294117647, 0.8970588235294118, 0.8852941176470588, 0.8764705882352941, 0.8941176470588236, 0.8676470588235294, 0.9117647058823529, 0.8823529411764706, 0.8735294117647059, 0.7735294117647059, 0.8588235294117647, 0.8735294117647059, 0.861764705882353, 0.85, 0.8852941176470588, 0.8941176470588236, 0.9088235294117647, 0.8970588235294118, 0.9147058823529411]\n"
     ]
    }
   ],
   "source": [
    "print(train_loss_list)\n",
    "print(test_loss_list)\n",
    "print(train_acc_list)\n",
    "print(test_acc_list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}